package com.tlvip.design.prototype;


/**
 * <p>description：</p>
 * <p>
 * 指原型实例指定创建对象的种类，并且通过拷贝这些原型创建新的对象
 * <p>
 * 对于可变的依赖对象，被依赖的对象需要实现Cloneable，并在依赖对象中重写Cloneable
 * <p>
 *  Spring AbstractBeanDefinition 自己实现了clone方法
 *  JDK java.utils.Array
 *  应用场景：当代码不应该依赖于需要复制的对象的具体类时，请使用原型模式
 *
 *  优点：
 *      可以不依赖具体类的情况下k克隆对象
 *      避免重复的初始化代码
 *      更方便的构建复杂对象
 *
 * 数组如何拷贝？
 *
 * <p>copyright： copyright(C)2016-2099</p>
 * <p>Life is short,we need passion</p>
 * <p>Summary： </p>
 * <p>instructions： </p>
 * Date 2021/8/15</p>
 * Author mac
 *
 * @version 1.0
 */
public class TestProtoType {
    public static void main(String[] args) throws CloneNotSupportedException {
        System.out.println("-------------原始对象信息---------------");
        BaseInfo baseInfo = new BaseInfo("b1", 2);
        Product product = new Product("part1", "part2", 3,baseInfo);
        System.out.println(product);
        System.out.println(baseInfo);
        System.out.println("---------------克隆后的对象信息-------------");
        Product productClone = (Product) product.clone();
        System.out.println(productClone);
        System.out.println(productClone.getBaseInfo());
        System.out.println("---------------修改原始对象BaseInfo信息-------------");
        baseInfo.setB1("bb1");
        System.out.println(product);
        System.out.println(baseInfo);
        System.out.println("---------------修改原始对象BaseInfo信息后，查看clone对象信息-------------");
        System.out.println(productClone);
        System.out.println(productClone.getBaseInfo());

    }
}

class BaseInfo implements Cloneable {
    private String b1;
    private Integer b2;

    public BaseInfo(String b1, Integer b2) {
        this.b1 = b1;
        this.b2 = b2;
    }

    public String getB1() {
        return b1;
    }

    public void setB1(String b1) {
        this.b1 = b1;
    }

    public Integer getB2() {
        return b2;
    }

    public void setB2(Integer b2) {
        this.b2 = b2;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return (BaseInfo) super.clone();
    }

    @Override
    public String toString() {
        return super.hashCode() + ",BaseInfo{" +
                "b1='" + b1 + '\'' +
                ", b2=" + b2 +
                '}';
    }
}

class Product implements Cloneable {
    private String part1;
    private String part2;
    private Integer part3;
    private BaseInfo baseInfo;

    public Product(String part1, String part2, Integer part3, BaseInfo baseInfo) {
        this.part1 = part1;
        this.part2 = part2;
        this.part3 = part3;
        this.baseInfo = baseInfo;
    }

    public String getPart1() {
        return part1;
    }

    public void setPart1(String part1) {
        this.part1 = part1;
    }

    public String getPart2() {
        return part2;
    }

    public void setPart2(String part2) {
        this.part2 = part2;
    }

    public Integer getPart3() {
        return part3;
    }

    public void setPart3(Integer part3) {
        this.part3 = part3;
    }

    public BaseInfo getBaseInfo() {
        return baseInfo;
    }

    public void setBaseInfo(BaseInfo baseInfo) {
        this.baseInfo = baseInfo;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        // 使用对象拷贝方式
        Product clone = (Product) super.clone();
        // 引用对象也进行拷贝，若不深度拷贝，将会在product的clone对象中公用相同的引用对象，存在风险
        BaseInfo bClone = (BaseInfo) clone.getBaseInfo().clone();
        clone.setBaseInfo(bClone);
        return clone;
    }

    @Override
    public String toString() {
        return super.hashCode() + ",Product{" +
                "part1='" + part1 + '\'' +
                ", part2='" + part2 + '\'' +
                ", part3=" + part3 +
                ", baseInfo=" + baseInfo +
                '}';
    }
}
